package com.cardone.platform.usercenter.service;

import java.util.List;
import java.util.UUID;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.cardone.common.dto.PaginationDto;
import com.cardone.context.ContextHolder;
import com.cardone.context.DictionaryException;
import com.cardone.platform.authority.dto.PermissionDto;
import com.cardone.platform.authority.service.PermissionService;
import com.cardone.platform.authority.service.RoleService;
import com.cardone.platform.authority.service.RoleUserService;
import com.cardone.platform.common.dto.EntityLogDto;
import com.cardone.platform.common.service.EntityLogService;
import com.cardone.platform.usercenter.dao.UserDao;
import com.cardone.platform.usercenter.dto.UserDto;
import com.cardone.platform.usercenter.po.User;

/**
 * 用户服务
 *
 * @author yaohaitao
 *
 */
@Getter
@Setter
@Transactional(readOnly = true)
public class UserDefaultService implements UserService {
	@Override
	@Transactional
	public int deleteByIds(final UserDto deleteUser) {
		return ContextHolder.getBean(UserDao.class).deleteByIds(deleteUser);
	}

	@Override
	public <P> P findByCodeForLogin(final Class<P> mappedClass, final UserDto findUser) {
		return ContextHolder.getBean(UserDao.class).findByCodeForLogin(mappedClass, findUser);
	}

	@Override
	public <P> P findByCodeOrId(final Class<P> mappedClass, final UserDto findUser) {
		return ContextHolder.getBean(UserDao.class).findByCodeOrId(mappedClass, findUser);
	}

	@Override
	public <P> P findById(final Class<P> mappedClass, final UserDto findUser) {
		if (StringUtils.isBlank(findUser.getId()) && StringUtils.isNotBlank(findUser.getLoginKey())) {
			final String userId = ContextHolder.getBean(EntityLogService.class).readEntityIdByIdForValid(findUser.getLoginKey());

			findUser.setId(userId);
		}

		final P p = ContextHolder.getBean(UserDao.class).findById(mappedClass, findUser);

		if (p == null) {
			return null;
		}

		if (!findUser.isLoadPermissionList()) {
			return p;
		}

		if (UserDto.class.equals(mappedClass)) {
			final UserDto user = (UserDto) p;

			final List<String> roleIdList = ContextHolder.getBean(RoleService.class).readIdListByUserId(user.getId());

			user.setRoleIdList(roleIdList);

			if (CollectionUtils.isEmpty(roleIdList)) {
				return p;
			}

			final List<PermissionDto> permissionList = ContextHolder.getBean(PermissionService.class).findListBySiteIdAndRoleIdList(PermissionDto.class, findUser.getSiteId(), roleIdList);

			user.setPermissionList(permissionList);
		}

		return p;
	}

	@Override
	public UserDto findById(final String id) {
		return ContextHolder.getBean(UserDao.class).findById(id);
	}

	@Override
	public UserDto findById(final UserDto findUser) {
		return ContextHolder.getBean(UserService.class).findById(UserDto.class, findUser);
	}

	@Override
	public <P> List<P> findListByLikeCode(final Class<P> mappedClass, final UserDto findListUser) {
		return ContextHolder.getBean(UserDao.class).findListByLikeCode(mappedClass, findListUser);
	}

	@Override
	@Transactional
	public int insertByCode(final UserDto insertUser) {
		return ContextHolder.getBean(UserDao.class).insertByCode(insertUser);
	}

	@Override
	@Transactional
	public UserDto login(final UserDto loginUser) {
		if (StringUtils.isBlank(loginUser.getCode())) {
			throw new DictionaryException("登录名不能为空");
		}

		if (StringUtils.isBlank(loginUser.getPassword())) {
			throw new DictionaryException("密码不能为空");
		}

		UserDto user = ContextHolder.getBean(UserService.class).findByCodeForLogin(UserDto.class, loginUser);

		if (user == null) {
			throw new DictionaryException("用户名或密码不正确，请重试");
		}

		if ("2".equals(user.getValidCode())) {
			throw new DictionaryException("帐号已过期").setTypeCode("login").setCode("valid");
		}

		if ((user.getLoginErrorCount() != null) && (user.getLoginErrorCount() > 5)) {
			throw new DictionaryException("登录失败超过5次，请3分钟后重试");
		}

		if (!StringUtils.equals(loginUser.getPassword(), user.getPassword())) {
			// 验证加密后密码是否相同
			final String loginPassword = DigestUtils.md5Hex(loginUser.getPassword());

			if (!StringUtils.equals(loginPassword, user.getPassword())) {
				throw new DictionaryException("用户名或密码不正确，请重试");
			}
		}

		loginUser.setId(user.getId());

		loginUser.setLoadPermissionList(true);

		user = ContextHolder.getBean(UserService.class).findById(loginUser);

		final int sitePermissionCount = CollectionUtils.isEmpty(user.getPermissionList()) ? 0 : user.getPermissionList().size();

		if (sitePermissionCount < 1) {
			throw new DictionaryException("无登录该系统的权限").setTypeCode("authority").setCode("notSite");
		}

		user.setLoginKey(UUID.randomUUID().toString());

		final EntityLogDto insertEntityLog = EntityLogDto.newEntityLog();

		insertEntityLog.setId(user.getLoginKey());
		insertEntityLog.setTypeTypeCode("log_type");
		insertEntityLog.setTypeCode("login");
		insertEntityLog.setCode("login");
		insertEntityLog.setUserId(user.getId());
		insertEntityLog.setEntityId(user.getId());

		ContextHolder.getBean(EntityLogService.class).saveByEntityIdAndTypeId(insertEntityLog);

		return user;
	}

	@Override
	public <P> PaginationDto<P> paginationByLikeCode(final Class<P> mappedClass, final UserDto paginationUser) {
		return ContextHolder.getBean(UserDao.class).paginationByLikeCode(mappedClass, paginationUser);
	}

	@Override
	public <P> PaginationDto<P> paginationByOrgIdAndLikeCode(final Class<P> mappedClass, final UserDto paginationUser) {
		return ContextHolder.getBean(UserDao.class).paginationByOrgIdAndLikeCode(mappedClass, paginationUser);
	}

	@Override
	public Integer readByCodeNqIdForCount(final UserDto readUser) {
		return ContextHolder.getBean(UserDao.class).readByCodeNqIdForCount(readUser);
	}

	@Override
	@Transactional
	public UserDto register(final UserDto registerUser) {
		UserDto loginUser = this.saveByCode(registerUser);

		UserDto user = ContextHolder.getBean(UserService.class).findById(loginUser);

		user.setLoginKey(UUID.randomUUID().toString());

		final EntityLogDto insertEntityLog = EntityLogDto.newEntityLog();

		insertEntityLog.setId(user.getLoginKey());
		insertEntityLog.setTypeTypeCode("log_type");
		insertEntityLog.setTypeCode("login");
		insertEntityLog.setCode("login");
		insertEntityLog.setUserId(user.getId());
		insertEntityLog.setEntityId(user.getId());

		ContextHolder.getBean(EntityLogService.class).saveByEntityIdAndTypeId(insertEntityLog);

		return user;
	}

	@Override
	@Transactional
	public UserDto saveByCode(final UserDto saveUser) {
		if (StringUtils.isBlank(saveUser.getCode())) {
			throw new DictionaryException("用户名不能为空值").setTypeCode(User.class).setCode("isBlankCode");
		}

		if (StringUtils.isBlank(saveUser.getPassword())) {
			throw new DictionaryException("密码不能为空值").setTypeCode(User.class).setCode("isBlankPassword");
		}

		final Integer userCount = ContextHolder.getBean(UserService.class).readByCodeNqIdForCount(saveUser);

		if (userCount > 0) {
			throw new DictionaryException("用户名已有，请修改用户名").setTypeCode(User.class).setCode("provenCode");
		}

		final String md5Password = DigestUtils.md5Hex(saveUser.getPassword());

		saveUser.setPassword(md5Password);

		ContextHolder.getBean(UserDao.class).insertByCode(saveUser);

		final UserDto user = ContextHolder.getBean(UserDao.class).findByCodeOrId(UserDto.class, saveUser);

		ContextHolder.getBean(RoleUserService.class).insertByRoleCode(saveUser.getRoleCodeList(), user.getId());

		return user;
	}

	@Override
	@Transactional
	public <P> P saveByIdOrCode(final Class<P> mappedClass, final UserDto saveUser) {
		return ContextHolder.getBean(UserDao.class).saveByIdOrCode(mappedClass, saveUser);
	}

	@Override
	@Transactional
	public int updateByCode(final UserDto updateUser) {
		return ContextHolder.getBean(UserDao.class).updateByCode(updateUser);
	}

	@Override
	public int updateEndDateByIdForInvalid(final String id) {
		return ContextHolder.getBean(UserDao.class).updateEndDateByIdForInvalid(id);
	}

	@Override
	@Transactional
	public int updateForBaseInfo(final UserDto updateUser, final Boolean updateMobilePhone) {
		if (StringUtils.isBlank(updateUser.getId())) {
			throw new DictionaryException("用户标识不能为空值").setTypeCode(User.class).setCode("isBlankId");
		}

		return ContextHolder.getBean(UserDao.class).updateForBaseInfo(updateUser, updateMobilePhone);
	}

	@Override
	public int updateForDetail(final UserDto updateUser) {
		if (StringUtils.isBlank(updateUser.getId())) {
			throw new DictionaryException("用户标识不能为空值").setTypeCode(User.class).setCode("isBlankId");
		}

		if (StringUtils.isNotBlank(updateUser.getPassword())) {
			final String md5Password = DigestUtils.md5Hex(updateUser.getPassword());

			updateUser.setPassword(md5Password);
		}

		return ContextHolder.getBean(UserDao.class).updateForDetail(updateUser);
	}

	@Override
	@Transactional
	public int updateForFullInfo(final UserDto updateUser, final Boolean updateMobilePhone) {
		if (StringUtils.isBlank(updateUser.getId())) {
			throw new DictionaryException("用户标识不能为空值").setTypeCode(User.class).setCode("isBlankId");
		}

		return ContextHolder.getBean(UserDao.class).updateForFullInfo(updateUser, updateMobilePhone);
	}

	@Override
	public int updateMobilePhone(final String id, final String mobilePhone) {
		return ContextHolder.getBean(UserDao.class).updateMobilePhone(id, mobilePhone);
	}

	@Override
	@Transactional
	public int updatePasswordById(final String id, final String newPassword) {
		if (StringUtils.isBlank(id)) {
			throw new DictionaryException("用户标识不能为空值").setTypeCode(User.class).setCode("isBlankId");
		}

		if (StringUtils.isBlank(newPassword)) {
			throw new DictionaryException("新密码不能为空值").setTypeCode(User.class).setCode("isBlankNewPassword");
		}

		final String md5NewPassword = DigestUtils.md5Hex(newPassword);

		final int updateCount = ContextHolder.getBean(UserDao.class).updatePasswordById(id, null, md5NewPassword);

		if (updateCount < 1) {
			throw new DictionaryException("用户标识不正确").setTypeCode(User.class).setCode("notId");
		}

		return updateCount;
	}

	// public static void main(String[] args) {
	// String md5NewPassword = DigestUtils.md5Hex("123456");
	// System.out.println(md5NewPassword);
	// }

	@Override
	@Transactional
	public int updatePasswordById(final String id, final String oldPassword, final String newPassword) {
		return this.updatePasswordById(id, oldPassword, newPassword, true);
	}

	@Override
	@Transactional
	public int updatePasswordById(final String id, final String oldPassword, final String newPassword, final Boolean isDiges) {
		if (StringUtils.isBlank(id)) {
			throw new DictionaryException("用户标识不能为空值").setTypeCode(User.class).setCode("isBlankId");
		}

		if (StringUtils.isBlank(newPassword)) {
			throw new DictionaryException("新密码不能为空值").setTypeCode(User.class).setCode("isBlankNewPassword");
		}

		String md5OldPassword = oldPassword;

		if (StringUtils.isNotBlank(oldPassword) && BooleanUtils.isTrue(isDiges)) {
			md5OldPassword = DigestUtils.md5Hex(oldPassword);
		}

		String md5NewPassword = newPassword;

		if (BooleanUtils.isTrue(isDiges)) {
			md5NewPassword = DigestUtils.md5Hex(newPassword);
		}

		final int updateCount = ContextHolder.getBean(UserDao.class).updatePasswordById(id, md5OldPassword, md5NewPassword);

		if (updateCount < 1) {
			throw new DictionaryException("旧密码不正确").setTypeCode(User.class).setCode("notOldPassword");
		}

		return updateCount;
	}
}